from lib2to3.fixes.fix_input import context
import decimal

from django.db import transaction
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.fields import SerializerMethodField
from rest_framework.serializers import ModelSerializer
from datetime import datetime
import random

from users.models import Address
from .models import Classification, Commodity, CommodityImg, ShoppingCart, Order, OrderGoods, Payment


# 分类的序列化器
class ClassificationsSerializer(ModelSerializer):
    class Meta:
        model = Classification
        fields = ["id","name"]


# 一级分类的序列化器
class ParentClassificationsSerializer(ModelSerializer):
    # 一级分类要展示所有的 子级分类
    classification_set = ClassificationsSerializer(many=True,read_only=True)

    class Meta:
        model = Classification
        fields = ["id","name","classification_set"]


# 商品图片序列化器
class CommodityImgSerializer(ModelSerializer):
    class Meta:
        model = CommodityImg
        fields = "__all__"

        extra_kwargs = {
            "priority":{"read_only" : True},
        }


class CommodityImgSerializerSimple(ModelSerializer):
    class Meta:
        model = CommodityImg
        exclude = ["created_time","update_time","is_delete","commodity","priority"]

        extra_kwargs = {
            "priority":{"read_only" : True},
        }

# 商品的序列化器
class CommoditySerializer(ModelSerializer):
    # 一级分类
    classification1_name = serializers.CharField(source="classification1.name",read_only=True)
    classification2_name = serializers.CharField(source="classification2.name",read_only=True)
    # 二级分类
    # 商品图片加入
    commodityimg_set = CommodityImgSerializerSimple(many=True,read_only=True)
    class Meta:
        model = Commodity
        exclude = ["is_delete"]

        extra_kwargs = {
            "sales" : {"read_only" : True},
            "comments":{"read_only" : True},
        }


# 购物车
class ShoppingCartSerializer(ModelSerializer):
    # 吧商品数据展示出来
    commodityDetail =  SerializerMethodField()
    class Meta:
        model = ShoppingCart
        fields = "__all__"

    def get_commodityDetail(self,shoppingcart):
        #  shoppingcart.commodity
        return CommoditySerializer(shoppingcart.commodity).data

    # # 库存的校验  商品表的库存数量   和 加入购物车的商品数量
    # {
    #     "id": 1,
    #     "created_time": "2025-04-14T20:17:23.888850",
    #     "update_time": "2025-04-14T20:17:23.888896",
    #     "number": 1,
    #     "commodity": 9,
    #     "user": 3
    # }
    def validate(self, attrs): #
        if attrs["number"] <=0 :
            raise serializers.ValidationError("购物车数量不能为0")
        elif attrs["number"] > attrs["commodity"].stock: # 购物车数量不能大于库存
            raise serializers.ValidationError("购物车不能超出商品数量")
        else:
            return attrs



# 订单的序列化器
class OrderSerializer(ModelSerializer):
    # 得到前端传入的多个商品的
    cart = serializers.ListField(write_only=True)
    class Meta:
        model = Order
        # 只读
        # extra_kwargs = {
        #     "order_id": {"read_only": True},
        # }
        fields = "__all__"
        read_only_fields = [
            "order_id",
            "total_count",
            "total_amount",
            "status",
            "user",
        ]

    # 创建订单
    def create(self, validated_data):
        # 得到用户信息  绑定为当前登录的用户
        user = self.context["request"].user
        # 生成订单号 根据当前的时间  + 6位用户id  + 随机数
        # "20250414205246"   "000005"  "02"
        order_id = datetime.now().strftime("%Y%m%d%H%M%S") + '%06d%02d' % (user.id,random.randint(1,99))
        # 支付方式
        pay_method = validated_data.get("pay_method")
        #  从地址模型里面 id 查询  address 前端传入的地址id
        # 得到地址模型对象  {"address":1}
        try:
            address= Address.objects.get(id = validated_data.get("address"))
        except Address.DoesNotExist:
            raise ValidationError("地址不存在")
        # 地址模型  省 市 区  详情  谁收  手机号
        address_s = f"""
                {address.province.name}       
        {address.city.name}       
        {address.district.name}       
        {address.place}       
        【{address.receiver}收】       
        {address.mobile}       
        """
        # 停单 撤销
        # 事务
        with transaction.atomic():
            # 创建一个节点   保存点
            save_point = transaction.savepoint()
            try:
                # 创建空白订单
                order = Order.objects.create(
                    order_id = order_id, # 订单id
                    total_count = 0,# 商品总数
                    total_amount = decimal.Decimal("0.00"),
                    pay_method = pay_method,
                    status =1 if pay_method == 1 else 2,
                    address = address_s,
                    user = user
                )

                #  得到所有的商品列表 进行循环结算
                # 前端传入的 [2，3，4]
                carts = validated_data.get("cart")


                # 循环的得到每一个购物车内数据id
                for cart_id in carts:
                    while True:
                    # 得到购物车里面的每一个商品的商品数据
                        try:
                            cart = ShoppingCart.objects.get(id = cart_id)
                        except ShoppingCart.DoesNotExist:
                            raise  serializers.ValidationError("购物车商品信息不存在")
                        # 得到商品模型对象
                        commodity = cart.commodity
                        # 在结算之前 所有要判断一下 商品的库存 和销量
                        origin_stock = commodity.stock
                        origin_sales = commodity.sales

                        # 核算一下是否超库存
                        if cart.number > origin_stock:
                            raise serializers.ValidationError("库存不足")

                        # 购买  库存减少  销量增加
                        # 新库存  =  原库存 -  购物车购买的商品数量
                        new_stock = origin_stock - cart.number
                        new_sales = origin_sales + cart.number

                        # 商品表修改了
                        # commodity.stock = new_stock
                        # commodity.sales = new_sales
                        # commodity.save()
                        res = Commodity.objects.filter(id = commodity.id,stock = origin_stock).update(stock = new_stock,sales = new_sales)
                        if not res: # 商品被更新了
                            continue
                        # 生成对应订单商品数据
                        OrderGoods.objects.create(
                            number= cart.number, #得到单个商品的数量
                            price = commodity.price,# 得到单个商品的价格
                            order = order,
                            commodity = commodity,
                        )

                        # 订单也要更新
                        # 订单总数
                        order.total_count += cart.number
                        # 订单总价
                        order.total_amount += (cart.number * commodity.price)
                        # 结束while 继续进入for循环
                        break

                # 购物车内所有的商品都循环结算后 订单保存
                order.save()
                # 购物车内的商品要进行清空
                ShoppingCart.objects.filter(id__in=carts).delete()
            except Exception as e:
                # 事务回滚
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError(e) #返回爆粗信息
            else:
                # 事务提交
                transaction.savepoint_commit(save_point)

        # 返回创建的订单
        return order



# 加锁
# 悲观锁  多个线程  线程 AB 获取同步锁
#       假设 A 加锁成功，执行操作  b处于等待（阻塞）状态  等a解锁之后 b才能操作

# 乐观锁  不加锁
#      线程a和b在进行同步更新的时候，都会判断这个数据是否被修改
#      如果修改了。就执行定义操作 或者报错

# 支付凭证的序列化器
class PaymentSerializer(ModelSerializer):
    class Meta:
        model = Payment
        fields = "__all__"
